#include <math.h>
#include "Header.h"

struct CompressorDataStruct
{
	int n;
	double threshold;
	double slope;
	int sr;
	double tla;
	double twnd;
	double tatt;
	double trel;
	double env;
	double inputGain;
	double outputGain;
} typedef CompressorData;

DECLSPEC void STDCALL Effect_Compressor_Process(CompressorData* data, double* wav_in_left, double* wav_in_right, double* wav_out_left, double* wav_out_right)
{
	int n = data->n;          // N samples
	double threshold = data->threshold;  // threshold (percents)
	double slope = data->slope;      // slope angle (percents)
	int sr = data->sr;         // sample rate (smp/sec)
	double tla = data->tla;        // lookahead  (ms)
	double twnd = data->twnd;       // window time (ms)
	double tatt = data->tatt;       // attack time  (ms)
	double trel = data->trel;       // release time (ms)

										   //typedef float stereodata[2];
	threshold *= 0.01;          // threshold to unity (0...1)
	slope *= 0.01;              // slope to unity
	tla *= 1e-3;                // lookahead time to seconds
	twnd *= 1e-3;               // window time to seconds
	tatt *= 1e-3;               // attack time to seconds
	trel *= 1e-3;               // release time to seconds

								// attack and release "per sample decay"
	double att = (tatt == 0.0) ? (0.0) : exp(-1.0 / (sr * tatt));
	double rel = (trel == 0.0) ? (0.0) : exp(-1.0 / (sr * trel));

	// sample offset to lookahead wnd start
	int lhsmp = (int)(sr * tla);

	// samples count in lookahead window
	int nrms = (int)(sr * twnd);

	// for each sample...
	for (int i = 0; i < n; ++i)
	{
		// now compute RMS
		double summ = 0;

		// for each sample in window
		for (int j = 0; j < nrms; ++j)
		{
			int lki = i + j + lhsmp;
			double smp;

			// if we in bounds of signal?
			// if so, convert to mono
			if (lki < n)
				smp = 0.5 * (wav_in_left[lki] * data->inputGain) + 0.5 * (wav_in_right[lki] * data->inputGain);
			else
				smp = 0.0;      // if we out of bounds we just get zero in smp

			summ += smp * smp;  // square em..
		}

		double rms = sqrt(summ / nrms);   // root-mean-square

		// dynamic selection: attack or release?
		double theta = rms > data->env ? att : rel;

		// smoothing with capacitor, envelope extraction...
		// here be aware of pIV denormal numbers glitch
		data->env = (1.0 - theta) * rms + theta * data->env;

		// the very easy hard knee 1:N compressor
		double gain = 1.0;
		if (data->env > threshold)
		{
			gain = gain - (data->env - threshold) * slope;
		}

		// result - two hard kneed compressed channels...
		*wav_out_left = wav_in_left[i] * data->inputGain * gain * data->outputGain;
		*wav_out_right = wav_in_right[i] * data->inputGain * gain * data->outputGain;
		*wav_out_left++;
		*wav_out_right++;
	}
}